#include "FLOAT.h"
FLOAT F_mul_F(FLOAT a, FLOAT b) {
//	nemu_assert(0);
	long long c = (long long) a * (long long ) b;
	FLOAT r = (FLOAT)(c>>16);
	return r;
}

FLOAT F_div_F(FLOAT a, FLOAT b) {
	/* Dividing two 64-bit integers needs the support of another library
	 * `libgcc', other than newlib. It is a dirty work to port `libgcc'
	 * to NEMU. In fact, it is unnecessary to perform a "64/64" division
	 * here. A "64/32" division is enough.
	 *
	 * To perform a "64/32" division, you can use the x86 instruction
	 * `div' or `idiv' by inline assembly. We provide a template for you
	 * to prevent you from uncessary details.
	 *
     asm volatile ("??? %2" : "=a"(???), "=d"(???) : "r"(???), "a"(???), "d"(???));
	 *
	 * If you want to use the template above, you should fill the "???"
	 * correctly. For more information, please read the i386 manual for
	 * division instructions, and search the Internet about "inline assembly".
	 * It is OK not to use the template above, but you should figure
	 * out another way to perform the division.
	 */
     //nemu_assert(0);
     FLOAT result ,rest  = 0;
     FLOAT dd=0;
      asm volatile ("idiv %2" : "=a"(result), "=d"(rest) : "r"(b), "a"(a<<16), "d"(a>>16));
      return result;
}

typedef union {  
    float f;  
    unsigned int i;  
} float_uint32_t;

FLOAT f2F(float a) {
	/* You should figure out how to convert `a' into FLOAT without
	 * introducing x87 floating point instructions. Else you can
	 * not run this code in NEMU before implementing x87 floating
	 * point instructions, which is contrary to our expectation.
	 *
	 * Hint: The bit representation of `a' is already on the
	 * stack. How do you retrieve it to another variable without
	 * performing arithmetic operations on it directly?
	 */

	//nemu_assert(0);
	//假设float转FLOAT不会溢出且都是规格化数
	
	float_uint32_t ss;
	 ss.f = a;
	 if(ss.i == 0){return ss.i;}
	unsigned int s = ss.i & 0x80000000;//符号位
	s = s >> 31;
    	unsigned int E = ss.i & 0x7f800000;//偏移后的指数位
	E = E>>23;
        unsigned int e = E - 127;
        unsigned int m = ss.i & 0x7fffff;//尾数小数部部分
        unsigned int b = 23 - e;//小数位数
        unsigned int mh =1;
		mh = mh << 23;
		mh = mh+m;
	unsigned int md;
	if(b>23){md=0;}
	else{	md = mh >>b;//存结果整数部分
	}

        unsigned int ml;
       if(b<32){ml	= mh << (32 - b); 
		ml = ml>> 16;}
       else{
	       ml = mh >> (b-32);
	       ml = ml >>16;}//存结果小数部分
	FLOAT r = (md << 16) | ml;
        //set_bp();
	if(s == 0 )
	{return r;}
	else{return -r;}	
}

FLOAT Fabs(FLOAT a) {
	//nemu_assert(0);
	int s = a&0x80000000;
	if(s == 0){return a;}
	else{
	FLOAT r = -a;
	return r;}
}

/* Functions below are already implemented */

FLOAT sqrt(FLOAT x) {
	//set_bp();
	FLOAT dt, t = int2F(2);
	//set_bp();
	do {
		
		dt = F_div_int((F_div_F(x, t) - t), 2);
	//set_bp();	
		t += dt;
	} while(Fabs(dt) > f2F(1e-4));
       
	return t;
}

FLOAT pow(FLOAT x, FLOAT y) {
	/* we only compute x^0.333 */
	FLOAT t2, dt, t = int2F(2);

	do {
		t2 = F_mul_F(t, t);
		dt = (F_div_F(x, t2) - t) / 3;
		t += dt;
	} while(Fabs(dt) > f2F(1e-4));

	return t;
}

